# _*_ coding: utf-8 _*_
"""
Time:     2024/9/14
Author:   2051261
File:     increment_where.py
"""
from __future__ import annotations
import typing as t
from datetime import datetime

from schematics.models import Model
from schematics.types import StringType
from schematics.types import IntType

from mine.db.db_operate import db_operate
from extractor.model.factory import SQLBuilderFactory
from extractor.flow.base_node_flow import BaseNodeFlow


if t.TYPE_CHECKING:
    from extractor.flow.node_model.log_node import RecordLog
    from extractor.flow.task_entry import Cache


async def _initialize_cache(inc_type: str):
    """
    根据列类型返回对应 0 值
    bigint、decimal、char类型支持 ""
    datetime 不支持
    若存在其他类型不支持
    :param inc_type:
    :return:
    """
    num_type = ["decimal", "int", "bigint"]
    if inc_type == "datetime":
        return datetime.strptime("0001-01-01 00:00:00", "%Y-%m-%d %H:%M:%S")
    if inc_type in num_type:
        return 0
    return ""


class IncrementWhereModel(Model):
    """
    节点所需的参数
    """
    inc_column: str = StringType(required=True)
    conn_name: str = StringType(required=True)
    table_name: str = StringType(required=True)
    inc_value: str = IntType()
    inc_format: str = StringType()
    src_conn_name: str = StringType()
    src_table_name: str = StringType()


class IncrementWhereNode(BaseNodeFlow):

    async def __call__(self, record_log: RecordLog, context, cache: Cache, record: t.DefaultDict, kwargs=None) -> \
            (t.Dict[str, t.Any] | t.Iterator[t.Dict[str, t.Any]] | None):
        """

        :param record_log: 日志操作的对象
        :param context: 任务运行时传递的上下文
        :param cache 缓存
        :param record 操作过程需要记录的值
        :param kwargs: 函数所需要的参数 与 IncrementWhereModel 对应
        :return:
        """
        model = IncrementWhereModel(kwargs)
        # Check cache
        cache_value = await cache.get_value()
        if cache_value is not None:
            await record_log.start({"inc": cache.get_value()})
            return context

        # 如果配置文件配置了缓存值(配置文件优先级最高)
        cache_value = model.inc_value
        if cache_value is not None:
            await cache.initialize(model.inc_column, cache_value)
            await record_log.start({"inc": cache_value})
            return context

        # 否则查库，看获取增量
        table_name, inc_column = model.table_name, model.inc_column
        conn_name = model.conn_name
        db_type = await db_operate.get_db_type(conn_name)
        sql_build = await SQLBuilderFactory().get_query_builder(db_type)
        sql = await sql_build.inc_query_sql(table_name, inc_column)
        result = await db_operate.fetch_one(conn_name, sql)
        value = result.get(inc_column)

        if value is None:
            src_db_type = await db_operate.get_db_type(model.src_conn_name or conn_name)
            src_sql_build = await SQLBuilderFactory().get_query_builder(src_db_type)
            sql = await src_sql_build.get_column_type(model.src_table_name or table_name, model.inc_column)
            column_type = await db_operate.fetch_one(model.src_conn_name or conn_name, sql)
            column_type = list(column_type.values())[0]
            value = await _initialize_cache(column_type)
        await cache.initialize(model.inc_column, value)

        await record_log.start({"inc": cache.get_value()})

        return context
